home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Practical Algorithms for Image Analysis
/
Practical Algorithms for Image Analysis.iso
/
TARFILE.GZ
/
tarfile
/
ch_3.1
/
xconv
/
xconv.c
< prev
next >
Wrap
C/C++ Source or Header
|
1999-09-11
|
7KB
|
300 lines
/*
* xconv.c
*
* Practical Algorithms for Image Analysis
*
* Copyright (c) 1997, 1998, 1999 MLMSoftwareGroup, LLC
*/
/*
* XCONV(olve)
*
* test convolve.c module
*
*/
#include "xconv.h"
#define BUFSZ 1024
#define MAX_FILTER_LENGTH 65
#undef FILTER_PRINT /* define this to print filter */
/*
* globals
*/
extern short tiffInput; /* flag=0 if no ImageIn to set tags; else =1 */
extern char *optarg;
extern int optind, opterr;
/*
* usage of routine
*/
void
usage (char *progname)
{
progname = last_bs (progname);
printf ("USAGE: %s inimg outimg [-f filter_file] [-g len] [-L]\n", progname);
printf ("\n%s convolves an image with a kernel;\n", progname);
printf ("kernels may be read from a filter file; Gaussian\n");
printf ("kernels of any length can be generated automatically.\n\n");
printf ("ARGUMENTS:\n");
printf (" inimg: intput image filename (TIF)\n");
printf (" outimg: output image filename (TIF)\n\n");
printf ("OPTIONS:\n");
printf (" -f filter_file: filename for filter to use (ASCII)\n");
printf (" -g len: use 2-D Gaussian filter of length len\n");
printf (" NOTE: either -f or -g must be specified\n");
printf (" -L: print Software License for this module\n");
exit (1);
}
#undef FILTER_TEST
Matrix *
genGaussFilter (char *filterLenStr)
{
Matrix *retMatrix;
float *ip, **ipp;
int ix, iy;
int i;
int nf2;
float two_sigma_sq;
float x;
float sigma;
float *filter1D;
float norm;
int filterLen;
if (!sscanf (filterLenStr, "%d", &filterLen)) {
printf ("Can't scan gaussian filter length\n");
exit (1);
}
if (filterLen > MAX_FILTER_LENGTH || filterLen < 0) {
printf ("\n...filter length too long!! forget it!!\n");
exit (1);
}
filterLen = (filterLen % 2 > 0 ? filterLen : (filterLen + 1));
sigma = (float) filterLen / (float) (3.0 * 2.0);
nf2 = filterLen / 2;
norm = (float) 0.0;
if ((retMatrix = (struct Matrix *) calloc (1, sizeof (struct Matrix))) == NULL) {
printf ("\n...mem allocation for retMatrix failed\n");
exit (1);
}
if ((ipp = (float **) calloc (filterLen, sizeof (float *))) == NULL) {
printf ("\n...mem allocation for ipp failed\n");
exit (1);
}
if ((ip = (float *) calloc (filterLen * filterLen, sizeof (float))) == NULL) {
printf ("\n...mem allocation for ip failed\n");
exit (1);
}
if ((filter1D = (float *) calloc (filterLen, sizeof (float))) == NULL) {
printf ("\n...mem allocation for filter1D failed\n");
exit (1);
}
for (iy = 0; iy < filterLen; iy++)
ipp[iy] = ip + (iy * filterLen);
retMatrix->matrix = ipp;
/*
* Generate a 1-D Gaussian
*/
two_sigma_sq = (float) 2.0 *sigma * sigma;
for (i = 0; i < filterLen; i++) {
x = (float) (i - filterLen / 2);
*(filter1D + i) = (float) (255.0 * exp (-(x * x) / two_sigma_sq));
norm += *(filter1D + i);
}
norm = (float) fabs ((double) norm);
/*
* Now create the 2-D kernel
*/
for (iy = 0; iy < filterLen; iy++)
for (ix = 0; ix < filterLen; ix++)
ipp[iy][ix] = (*(filter1D + iy) * *(filter1D + ix));
#ifdef FILTER_PRINT
printf ("...sigma = %f\n", sigma);
printf ("...filter length = %d\n", filterLen);
printf ("...kernel coefficients:\n");
for (iy = 0; iy < filterLen; iy++) {
for (ix = 0; ix < filterLen; ix++)
printf ("%5.5f ", ipp[iy][ix]);
printf ("\n");
}
#endif
retMatrix->nRows = filterLen;
retMatrix->nCols = filterLen;
return (retMatrix);
}
Matrix *
readFilter (char *filename)
{
FILE *stream;
int nx, ny;
Matrix *retMatrix;
float *ip, **ipp;
int ix, iy;
char *sptr, inBuf[BUFSZ];
char seps[] = " ,\t\n";
char *token;
if ((stream = fopen (filename, "r")) != NULL) {
for (;;) {
if (fgets (inBuf, BUFSZ, stream) == (char *) NULL) {
printf ("Premature EOF encountered while reading filter file %s\n", filename);
exit (1);
}
/*
* Throw away comments
*/
if (inBuf[0] == '#')
continue;
else {
if (sscanf (inBuf, "%d %d\n", &nx, &ny) != 2) {
printf ("error getting kernel size\n");
exit (1);
}
if ((retMatrix = (struct Matrix *) calloc (1, sizeof (struct Matrix))) == NULL) {
printf ("\n...mem allocation for retMatrix failed\n");
exit (1);
}
if ((ipp = (float **) calloc (ny, sizeof (float *))) == NULL) {
printf ("\n...mem allocation for ipp failed\n");
exit (1);
}
if ((ip = (float *) calloc (ny * nx, sizeof (float))) == NULL) {
printf ("\n...mem allocation for ip failed\n");
exit (1);
}
for (iy = 0; iy < ny; iy++)
ipp[iy] = ip + (iy * nx);
retMatrix->matrix = ipp;
break;
}
}
/*
* Now read the kernel in
*/
for (iy = 0; iy < ny; iy++) {
if (fgets (inBuf, BUFSZ, stream) == (char *) NULL) {
printf ("Premature EOF encountered while reading filter file %s\n", filename);
exit (1);
}
/*
* Throw away comments
*/
if (inBuf[0] == '#')
continue;
sptr = inBuf;
for (ix = 0; ix < nx; ix++) {
if ((token = strtok (sptr, seps)) == (char *) NULL) {
printf ("Can't read filter values on line %d of file %s\n", iy + 2, filename);
exit (1);
}
if (!sscanf (token, "%f", &(ipp[iy][ix]))) {
printf ("Can't scan filter values on line %d of file %s\n", iy + 2, filename);
exit (1);
}
sptr = NULL;
}
}
fclose (stream);
retMatrix->nRows = ny;
retMatrix->nCols = nx;
for (iy = 0; iy < ny; iy++) {
for (ix = 0; ix < nx; ix++)
printf ("%5.5f ", ipp[iy][ix]);
printf ("\n");
}
return (retMatrix);
}
else {
printf ("Can not open kernel file: %s\n", filename);
exit (1);
}
}
int
main (int argc, char *argv[])
{
Image *imgIn, *imgOut;
Matrix *kernelp;
int kernel_gauss = 0;
int kernel_file = 0;
int i_arg;
/*
* cmd line options:
*/
static char *optstring = "f:g:L";
/*
* parse command line
*/
optind = 3;
opterr = ON; /* give error messages */
if (argc < 4)
usage (argv[0]);
while ((i_arg = getopt (argc, argv, optstring)) != EOF) {
switch (i_arg) {
case 'f':
/*
* Read in filter from file
*/
kernelp = readFilter (optarg);
kernel_file = 1;
break;
case 'g':
/*
* Generate 2-D Gaussian
*/
kernelp = genGaussFilter (optarg);
kernel_gauss = 1;
break;
case 'L':
print_sos_lic ();
exit (0);
default:
usage (argv[0]);
break;
}
}
if (kernel_gauss && kernel_file) {
printf ("Please specify either -f OR -g option, not both!\n");
exit (1);
}
/*
* read input image
*/
imgIn = ImageIn (argv[1]);
if (imgIn->bps == 8 && imgIn->spp == 3) {
printf ("Got RGB image!!!\nInput image must be Grayscale or B&W!!\n");
exit (1);
}
/* reset tiffInput so that we write a grayscale file (i.e tags are not copied) */
tiffInput = 0;
/*
* Allocate memory for output image
*/
imgOut = ImageAlloc (imgIn->height, imgIn->width, imgIn->bps);
printf ("Doing image convolution...\n");
/*
* Do the convolution
*/
convolve (imgIn, imgOut, kernelp);
/*
* Write the output image
*/
ImageOut (argv[2], imgOut);
return (1);
}